#include "Estacionamiento.h"

Estacionamiento::Estacionamiento(int cantidadLugares, double precioPorHora) {
	this->cantidadLugares = cantidadLugares;
	this->plazasEstacionamiento.crear(
			Utils::NOMBRE_ARCHIVO_PARA_PLAZAS_ESTACIONAMIENTO_MC,
			Utils::LETRA_PARA_PLAZAS_ESTACIONAMIENTO_MC, 2);
	for (int i = 0; i < cantidadLugares; i++) {
		PlazaEstacionamiento plaza(i);
		this->plazasEstacionamiento.escribir(cantidadLugares, plaza);
	}
	this->administrador = new Administrador(precioPorHora);
	this->lockEstacionamiento = new LockFile(
			Utils::NOMBRE_ARCHIVO_PARA_LOCK_MAPA_ESTACIONAMIENTO);
}

int Estacionamiento::getCantidadLugares() {
	return this->cantidadLugares;
}

Administrador Estacionamiento::getAdministrador() {
	return *this->administrador;
}

void Estacionamiento::sacarAuto(Auto * autoSalido) {
	this->desocuparPlaza(autoSalido->getPos());
	this->administrador->sacarAuto(autoSalido);
}

void Estacionamiento::lockPlaza(int pos) {
	this->lockEstacionamiento->tomarLock(pos);
}

void Estacionamiento::unlock(int pos) {
	this->lockEstacionamiento->liberarLock(pos);
}

void Estacionamiento::desocuparPlaza(int pos) {
	this->lockPlaza(pos);
	PlazaEstacionamiento * plaza;
	plaza = this->plazasEstacionamiento.leer(pos);
	plaza->desocupar();
	this->plazasEstacionamiento.escribir(pos, *plaza);
	//cout<<"desocupe la posicion: "<<pos<<endl;
	this->unlock(pos);
}

void Estacionamiento::ocuparPlaza(int pos) {
	this->lockPlaza(pos);
	PlazaEstacionamiento * plaza;
	plaza = this->plazasEstacionamiento.leer(pos);
	plaza->ocupar();
	this->plazasEstacionamiento.escribir(pos, *plaza);
	this->unlock(pos);
}

int Estacionamiento::getPosicionLibre() {
	if (this->cantidadLugares == this->administrador->consultarCantidadAutos())
		return -1;
	int pos;
	pos = Utils::calcularRandom(this->cantidadLugares);
	this->lockPlaza(pos);
	PlazaEstacionamiento * plaza = this->plazasEstacionamiento.leer(pos);
	if (plaza->isOcupado()) {
		this->unlock(pos);
		pos = this->getPosicionLibre();
	} else {
		plaza->ocupar();
		this->plazasEstacionamiento.escribir(pos, *plaza);
		this->unlock(pos);
	}
	return pos;
}

void Estacionamiento::estaciona(Auto * autoEntrando) {
	this->administrador->entraAuto();
}

void Estacionamiento::liberarMemoria() {
	this->administrador->liberarMemoria();
	this->plazasEstacionamiento.liberar();
}

Estacionamiento::~Estacionamiento() {
	this->plazasEstacionamiento.liberar();
	delete this->lockEstacionamiento;
	delete this->administrador;
}

